せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Ruby】パーフェクトRuby 学習感想文 ~第15章 その5

それでは15章を読んでいきます。

(参考・経緯など)
パーフェクトRuby 学習感想文 ~はじめに


 
P561 コードが間違えてる?(わけではなかった)その1

一部簡略化してますが↓

def self.parse!(argv)
	options = {}
	
	sub_cps = create_sub_cp(options)
	cp = create_cp  ←(ア)
	
	begin
	・・・
	end
	options
end

def self.create_sub_cp(options)
・・・
end

def self.create_cp(options)  ←(イ)
・・・
end

(イ)で引数ありのcreate_cpメソッドを定義していて、
(ア)で引数渡してないんだけど。
これ、絶対エラーなるよね・・・?
どうなってるんだろう?
 
(12月23日追記)--------------------
create_command_parser とcreate_command_parsers と2つのメソッド名を同一と勘違いしていました。。
(イ)のコードは正しくは「self.create_cps(options)」でした。とほほ。
 -------------------------------------

P561ではリファクタリング(処理を外部メソッドに切り出し)を行っているけど、
リファクタした後って必ず、
前と挙動が変わっていない(=このリファクタリングは実装を壊していない)
ことを示すべきでは。


メソッド切り出しを終えると、次のステップに進んじゃってて、
さりげなくOptions#parse!メソッドの
返り値も変更されてる(最終行のoptionsが消されている)し、
安全な行動だったのか分からないよー。

素人目ではエラーになるようにしか見えないし。。



 
P562 コードが間違えてる?(わけではなかった)その2
一部簡略化していますが、このコード↓

sub_cps = create_sub_cp(options)

・・・
def self.create_sub_cp(options)
	sub_cps = Hash.new
	
	sub_cps['create'] = OptionParser.new do |opt|
		opt.on('-n VAL', '--name=VAL', 'task name') {|v| options[:name] = v}
		opt.on('-c VAL', '--content=VAL', 'task content') {|v| options[:content] = v}
	end
end

こう書かないとエラーだと思う。実際エラーでした。↓

sub_cps = create_sub_cp(options)

・・・
def self.create_sub_cp(options)
	sub_cps = Hash.new 
	
	sub_cps['create'] = OptionParser.new do |opt|
		opt.on('-n VAL', '--name=VAL', 'task name') {|v| options[:name] = v}
		opt.on('-c VAL', '--content=VAL', 'task content') {|v| options[:content] = v}
	end
	sub_cps  ←この行追加
end

Hashインスタンスを返り値にするためには、hashインスタンスを最終行に書かないと。
このままだとsub_cps['create']のvalue値が返ってるよ(※1)


(12月23日追記)--------------------
p562のコードには「#...省略」となっていた中に、くだんのsub_command_parsers が記載されている事をサンプルコードにて確認しました。
「サブコマンドの定義方法」だけに記載内容をしぼっている結果の省略だと、今では分かるけれども、
慣れないうちは、、ねー。
 -------------------------------------

 
■最終行追加前

irb(main):002:0> TodoSamp::Command::Options.parse!(['create', '-n name_val'])
undefined method `[]' for #<OptionParser:0x397ecd8>


■修正後

irb(main):002:0>  TodoSamp::Command::Options.parse!(['create', '-n name_val'])
=> {:comand=>"create", :name=>" name_val"}

あ、create_cpメソッドの引数定義も削除したよ。



(※1)
念のため確認した↓

class Hoge
	def self.test
		hash = Hash.new
		hash['aa'] =1
		hash
	end
end
 
p Hoge.test

■実行結果

{"aa"=>1}


 

class Hoge
	def self.test
		hash = Hash.new
		hash['aa'] =1
	end
end
 
p Hoge.test

■実行結果

1


 
どうなってるんだ。。。
これじゃ闇鍋や。。。